﻿using System;
using System.Collections.Generic;
using System.Linq;
using AidBrella.BLL;
using AidBrella.Enums;
using AidBrella.Models;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;


namespace AidBrella.ViewModels
{
    #region ProjectViewModel
    public class ProjectViewModel:BaseViewModel
    {
        public string Name { get; set; }
        public int ProjectSectorId { get; set; }
        public string Description { get; set; }
        public int Id { get; set; }
        public string ProjectAddedBy { get; set; }

        public List<SelectListItem> Countries { get; set; }
        public string SelectedCountry { get; set; }
        public LocationViewModel Location { get; set; }
        public List<SelectListItem> ProjectSectorSelection { get; set; }
        public string ProjectSectorInString { get; set; }
        public int ProjectCreatedBy { get; set; }
        public bool UserCanUpdateThis { get { return UserId == ProjectCreatedBy; } }
        public bool UserIsFollowingProject { get; set; }

        [Display(Name= "Date started")]
        public DateTime? StartDate { get; set; }

        [Display(Name = "Date ended/ expected to end")]
        public DateTime? EndDate { get; set; }

        public string FollowState
        {
            get
            {
                if (!UserIsFollowingProject)
                    return "Follow";
               
               return "Unfollow";
            }
        }

        public Enums.UserRoleType UserBelongsToProjectAs { get; set ; }

        public List<UserViewModel> Members { get; set; }

      
    } 
    #endregion


   

    public class LocationViewModel
    {
        public double Longitude { get; set; }
        public double Latitude { get; set; }
    }

    public class MappableViewModel
    {
        public string Name { get; set; }
        public string Description { get; set; }
        public string Sector { get; set; }
        public string Contact { get; set; }
        public double Longitude { get; set; }
        public double Latitude { get; set; }
        public string Duration { get; set; }
        public List<UserViewModel> Members { get; set; }
        public int Count { get; set; }
        public int Id { get; set; }

        public List<FeedViewModel> Feeds { get; set; }
       
    }

   

    public class ProjectViewModelService
    {
        private readonly ProjectModel _model;
        private readonly UserModel _userModel;
        public ProjectViewModelService()
        {
            _model = new ProjectModel(); 
            _userModel = new UserModel();
        }

        /// <summary>
        /// Returns List of project feeds in FeedViewModel collection
        /// </summary>
        /// <param name="projectId"></param>
        /// <returns></returns>
        public List<FeedViewModel> GetFeedsByProject(int projectId)
        {
            var feedViewModels = new List<FeedViewModel>();
            FeedViewModel feedViewModel;

            var feeds = _model.GetProjectFeeds(projectId);

            foreach (var feed in feeds)
            {
                feedViewModel = new FeedViewModel
                {
                    ProjectId = projectId,
                    StatusBy = _userModel.GetUserFullNameById(feed.SubmitedBy),
                    StatusMessage = feed.Feed,
                    ProjectLogo = _model.GetProjectLogo(projectId),
                    FeedId = feed.Id,
                    PostedDate = feed.SubmitedOn.ToString("dd-MM-yyyy")
                };

                foreach (var cmt in feed.ProjectFeedCommentSet)
                {
                    var commentViewModel = new CommentViewModel
                    {
                        CommentId = cmt.Id,
                        CommentBy = _userModel.GetUserFullNameById(cmt.CommentBy),
                        CommentMessage = cmt.Comment
                    };
                    feedViewModel.Comments.Add(commentViewModel);
                }
                feedViewModels.Add(feedViewModel);

            }

            return feedViewModels;
        }

        /// <summary>
        /// Returns all Projects (Main usage in listing Projects /tags)
        /// </summary>
        /// <returns></returns>
        public IEnumerable<ProjectViewModel> GetProjects(int userId)
        {
            var projects = _model.GetProjects();
            var models = new List<ProjectViewModel>();

            ProjectViewModel pvm = null;
            foreach (var item in projects)
            {
                if (item.CreatedBy != null)
                    pvm = new ProjectViewModel
                              {
                                  Id = item.Id,
                                  Name = item.Name,
                                  Description = item.Description,
                                  ProjectCreatedBy = item.CreatedBy.Value,
                                  ProjectAddedBy = GetOwnerForProject(item.CreatedBy.Value),
                                  UserIsFollowingProject = IsUserFollowingThisProject(item.Id,userId),
                                  UserBelongsToProjectAs = GetUserProjectRole(userId,item.Id)
                              };

                if (item.ProjectSectorId == null) continue;
                if (pvm == null) continue;
                pvm.ProjectSectorId = item.ProjectSectorSet.Id;
                models.Add(pvm);
            }

            return models;
        }

        public Enums.UserRoleType GetUserProjectRole(int userId, int projectId)
        {
            const UserRoleType role = Enums.UserRoleType.None;
            var pm =  _model.GetEntities().ProjectMembers.Where(m => m.UserId == userId && m.ProjectId == projectId);
            if (pm.Count() == 0) return role;
            else
              return (UserRoleType) pm.FirstOrDefault().RoleId;
        }

        private static string GetOwnerForProject(int userId)
        {
            var um = new UserModel();
            var user = um.GetEntities().UserSet.Where((u=> u.Id == userId));
            return user.Count() == 1 ? string.Format(" Created by:  {0} {1}", user.FirstOrDefault().FirstName, user.FirstOrDefault().LastName) : " Created by: ananymous";
        }

        private static string GetOwnerOfProject(int userId)
        {
            var um = new UserModel();
            var user = um.GetEntities().UserSet.Where((u => u.Id == userId));
            return user.Count() == 1 ? string.Format("{0} {1}", user.FirstOrDefault().FirstName, user.FirstOrDefault().LastName) : " Created by: ananymous";
        }

        /// <summary>
        /// Returns all projects with a lightweight information that can be dispalyed on Map view
        /// </summary>
        /// <returns></returns>
        public IEnumerable<MappableViewModel> GetProjectsOnMap()
        {
            var points = new List<MappableViewModel>();
            var projects = _model.GetProjects();
            MappableViewModel point;

            foreach (var item in projects)
            {
                point = new MappableViewModel();
                point.Id = item.Id;
                point.Name = item.Name;
                point.Description = item.Description;
                point.Sector = item.ProjectSectorSet.Name;
                if (item.CreatedBy != null) point.Contact = GetOwnerOfProject(item.CreatedBy.Value);
                point.Duration = GetProjectDuration(item.StartDate, item.EndDate);
                point.Members = GetProjectMembers(item.Id);
                point.Count = _model.GetEntities().UserFollowProject.Where(p => p.ProjectId == item.Id).Count();
                point.Feeds = GetFeedsByProject(item.Id);
                if (item.ProjectSectorId == null) continue;
                var site = item.ProjectSiteSet.Where(o => o.ProjectSet_Id == item.Id).FirstOrDefault();
                if (site != null)
                {
                    point.Longitude = site.Longitude;
                    point.Latitude = site.Latitude;
                }
                points.Add(point);
            }

            return points;
        }

        private static string GetProjectDuration(DateTime? startDate, DateTime? endDate)
        {
            if (startDate != null)
                if (endDate != null)
                    return string.Format("{0} - {1}", startDate.Value.ToString("dd-MM-yyyy"), endDate.Value.ToString("dd-MM-yyyy"));

            return null;
        }


        public IEnumerable<MappableViewModel> GetUserProjectsOnMap(int userId)
        {
            var points = new List<MappableViewModel>();
            var projects = _model.GetProjectsUserIsInvolved(userId);

           
            MappableViewModel point;

            foreach (var item in projects)
            {
                point = new MappableViewModel();
                point.Id = item.Id;
                point.Name = item.Name;
                point.Description = item.Description;

                if (item.ProjectSectorId == null) continue;
                var site = item.ProjectSiteSet.Where(o => o.ProjectSet_Id == item.Id).FirstOrDefault();
                if (site != null)
                {
                    point.Longitude = site.Longitude;
                    point.Latitude = site.Latitude;
                }
                points.Add(point);
            }

            return points;
        }

        /// <summary>
        /// Returns a ProjectViewModel for requested projectId and optional userId
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public ProjectViewModel GetProject(int id, int userId = -1)
        {
            
            //if (userId != -1)
            //{
            //}

            var p = _model.GetProject(id);
            if (p != null)
            {
                if (p.CreatedBy != null)
                {
                    var project = new ProjectViewModel 
                                      { 
                                          Name = p.Name,
                                          Description = p.Description,
                                          ProjectSectorId = p.ProjectSectorSet.Id,
                                          Id = p.Id,
                                          ProjectSectorInString = p.ProjectSectorSet.Name,
                                          ProjectCreatedBy = p.CreatedBy.Value,
                                          UserIsFollowingProject = IsUserFollowingThisProject(id,userId),
                                          StartDate = p.StartDate, 
                                          EndDate = p.EndDate,
                                          UserId = userId != -1 ? userId : 0,
                                          ProjectAddedBy = GetOwnerForProject(p.CreatedBy.Value),
                                          UserBelongsToProjectAs = GetUserProjectRole(userId,p.Id),
                                          Members = GetProjectMembers(p.Id)
                                      };


                    return project;
                }
            }
            return null;
        }

        

        private List<UserViewModel> GetProjectMembers(int projectId)
        {
            var members = new List<UserViewModel>();

            var pm = _model.GetEntities().ProjectMembers.Where(u => u.ProjectId == projectId);
            var createdBy = _model.GetProject(projectId).CreatedBy;

            var creator = _model.GetEntities().UserSet.Where(u => u.Id == createdBy).FirstOrDefault();
            var uu = new UserViewModel
                         {
                             FirstName = creator.FirstName,
                             LastName = creator.LastName,
                             Email = creator.Email,
                             MemberAs = "Initiated Project",
                             UserId = creator.Id,
                             UserName = creator.UserName
                         };

            members.Add(uu);

            foreach (var projectMember in pm)
            {
                var u = new UserViewModel
                            {
                                FirstName = projectMember.UserSet.FirstName,
                                LastName = projectMember.UserSet.LastName,
                                Email = projectMember.UserSet.Email,
                                MemberAs = projectMember.UserProjectRole.Name,
                                UserId = projectMember.UserId,
                                UserName = projectMember.UserSet.UserName
                            };

                members.Add(u);
            }
            return members;
        }

        private bool IsUserFollowingThisProject(int projectId, int userId)
        {
            return GetProjectsUserIsFollowing(userId).Any(o => o.Id == projectId);       
        }

        /// <summary>
        /// Updates the information of a given Project 
        /// </summary>
        /// <param name="projectToUpdate"></param>
        public void UpdateProject(ProjectViewModel projectToUpdate)
        {
            ProjectSet p = _model.GetProject(projectToUpdate.Id);
            p.Name = projectToUpdate.Name;
            p.StartDate = projectToUpdate.StartDate;
            p.EndDate = projectToUpdate.EndDate;
            p.Description = projectToUpdate.Description;
            _model.SaveChanges();
        }

        /// <summary>
        /// Adds a new Project with the passed information
        /// </summary>
        /// <param name="newProject"></param>
        public void CreateProject(ProjectViewModel newProject)
        {
            
            var p = new ProjectSet
            {
                Name = newProject.Name,
                Description = newProject.Description,
                ProjectSectorId = newProject.ProjectSectorId,
                CreatedBy = newProject.UserId,
                StartDate = newProject.StartDate,
                EndDate = newProject.EndDate
            };

            var site = new ProjectSiteSet { Latitude = newProject.Location.Latitude, Longitude = newProject.Location.Longitude };
            
          
            _model.AddProject(p, site);

            var memb = new ProjectMembers
            {
                ProjectId = p.Id,
                RoleId = 1,
                UserId = p.CreatedBy.Value
            };

            _model.GetEntities().ProjectMembers.AddObject(memb);
            _model.SaveChanges();
        }

        public List<SelectListItem> GetProjectSectorSelectionList(int id = -1, bool check = false)
        {
            var sect = _model.GetProjectSectors();
            SelectListItem listItem;
            var en = new List<SelectListItem>();
            foreach (var item in sect)
            {
                listItem = new SelectListItem {Text = item.Name, Value = item.Id.ToString()};
                if (check && item.Id == id)                                  
                    listItem.Selected = true ;
                
                en.Add(listItem);
            }
            return en;
        }

        //public List<SelectListItem> GetJoinAsSelectionList(int id = -1, bool check = false)
        //{
        //    var sect = Enum.GetValues(typeof(AidBrella.Enums.UserRoleType));
        //    var en = new List<SelectListItem>();
        //    foreach (var item in sect)
        //    {
        //        var listItem = new SelectListItem { Text = item.ToString(), Value = item.ToString() };

        //        en.Add(listItem);
        //    }
        //    return en;
        //}


        /// <summary>
        /// Returns Projects User has created /in the future support for (joined also)
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public List<ProjectViewModel> GetProjectsUserHasCreated(int userId)
        {
            var projects = _model.GetProjectsUserIsInvolved(userId);

            return projects.Select(item => GetProject(item.Id)).ToList();
        }

        public List<ProjectViewModel> GetProjectsUserIsFollowing(int userId)
        {
           var projectmodels = new List<ProjectViewModel>();
            var projects = _model.GetProjectsUserFollow(userId);

            foreach (var model in projects.Select(item => GetProject(item.Id)))
            {
                model.UserIsFollowingProject = true;
                projectmodels.Add(model);
            }

            return projectmodels;
        }




        /// <summary>
        /// Adds a user to a UserProjectRole
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="projectId"></param>
        /// <param name="userRoleType"></param>
        public void JoinProject(int userId, int projectId ,Enums.UserRoleType userRoleType)
        {
            _model.JoinProject(userId, projectId, userRoleType);
        }
    }

    
    
}